import hashlib
import os
import time
from urllib import parse

from django.conf import settings
from django.contrib.admin.views.decorators import staff_member_required
from django.core.paginator import Paginator
from django.shortcuts import render
from django.utils.datetime_safe import datetime
from django.utils.timezone import make_aware
from django.views.decorators.http import require_GET, require_POST
from django.views.generic.base import View

from apps.articles.forms import ArticleCategoryForm, EditArticleCategoryForm, WriteArticleForm, AddBannerForm, \
    EditBannerForm
from apps.articles.models import ArticleCategory, Article, Banner
from apps.articles.serializers import BannersListSerializer
from apps.cms.forms import EditArticleForm
from utils import restful


def login_view(request):
    """
    测试
    :param request:
    :return:
    """
    return render(request, 'cms/cms_login.html')

@staff_member_required(login_url='index')
def index(request):
    """
    cms首页
    :param request:
    :return:
    """
    return render(request, 'cms/index.html')

class WriteArticle(View):
    """
    写文章
    """
    def get(self, request):
        categories = ArticleCategory.objects.all()
        context = {
            'categories': categories
        }
        return render(request, 'cms/write_article.html', context=context)

    def post(self, request):
        form = WriteArticleForm(request.POST)
        if not form.is_valid():
            errors = form.get_error()
            return restful.params_error(message=errors)
        title = form.cleaned_data.get('title')
        desc = form.cleaned_data.get('desc')
        thumbnail = form.cleaned_data.get('thumbnail')
        content = form.cleaned_data.get('content')
        category_id = form.cleaned_data.get('category')
        category = ArticleCategory.objects.get(pk=category_id)
        Article.objects.create(title=title, desc=desc, thumbnail=thumbnail,
                               content=content, category=category, author=request.user)
        return restful.ok()

class EditArticleView(View):
    """
    编辑文章接口
    """
    def get(self, request):
        article_id = request.GET.get('article_id')
        article = Article.objects.get(pk=article_id)
        context = {
            'article': article,
            'categories': ArticleCategory.objects.all()
        }
        return render(request, 'cms/write_article.html', context=context)

    def post(self, request):
        form = EditArticleForm(request.POST)
        if form.is_valid():
            title = form.cleaned_data.get('title')
            desc = form.cleaned_data.get('desc')
            thumbnail = form.cleaned_data.get('thumbnail')
            content = form.cleaned_data.get('content')
            category_id = form.cleaned_data.get('category')
            pk = form.cleaned_data.get("pk")
            category = ArticleCategory.objects.get(pk=category_id)
            Article.objects.filter(pk=pk).update(title=title, desc=desc, thumbnail=thumbnail, content=content, category=category)
            return restful.ok()
        else:
            return restful.params_error(message=form.get_errors())

@require_POST
def delete_article(request):
    article_id = request.POST.get('article_id')
    Article.objects.filter(pk=article_id).update(delete=True)
    return restful.ok()

@require_GET
def article_category(request):
    """
    文章分类页面
    :param request:
    :return:
    """
    categories = ArticleCategory.objects.all()
    context = {
        'categories': categories
    }
    return render(request, 'cms/article_category.html', context=context)

@require_POST
def add_article_category(request):
    """
    添加文章分类接口
    :param request:
    :return:
    """
    form = ArticleCategoryForm(request.POST)
    if not form.is_valid():
        return restful.params_error(message='最大字符长度不超过10个')
    name = form.cleaned_data.get('name')
    exists = ArticleCategory.objects.filter(name=name).exists()
    if exists:
        return restful.params_error(message='该分类已存在')
    ArticleCategory.objects.create(name=name)
    return restful.ok()

@require_POST
def edit_article_category(request):
    """
    跟新文章分类接口
    :param request:
    :return:
    """
    form = EditArticleCategoryForm(request.POST)
    if not form.is_valid():
        errors = form.get_error()
        return restful.params_error(message=errors)
    pk = form.cleaned_data.get('pk')
    name = form.cleaned_data.get('name')
    try:
        ArticleCategory.objects.filter(pk=pk).update(name=name)
    except:
        return restful.params_error(message='该分类不存在')
    return restful.ok()

@require_POST
def delete_article_category(request):
    """
    删除文章分类接口
    :param request:
    :return:
    """
    pk = request.POST.get('pk')
    try:
        ArticleCategory.objects.filter(pk=pk).delete()
        return restful.ok()
    except:
        return restful.params_error(message='该分类不存在')

def banners(request):
    """
    返回轮播图管理界面
    :param request:
    :return:
    """
    return render(request, 'cms/banners.html')

def banner_list(request):
    """
    获得所有的轮播图
    :param request:
    :return:
    """
    all_banner = Banner.objects.all()
    serializer = BannersListSerializer(all_banner, many=True)
    return restful.result(data=serializer.data)

def delete_banner(request):
    """
    删除轮播图接口
    :param request:
    :return:
    """
    banner_id = request.POST.get('banner_id')
    Banner.objects.filter(pk=banner_id).delete()
    return restful.ok()

def edit_banner(request):
    """
    编辑轮播图接口
    :param request:
    :return:
    """
    form = EditBannerForm(request.POST)
    if form.is_valid():
        pk = form.cleaned_data.get('pk')
        image_url = form.cleaned_data.get('image_url')
        link_to = form.cleaned_data.get('link_to')
        priority = form.cleaned_data.get('priority')
        Banner.objects.filter(pk=pk).update(image_url=image_url, link_to=link_to, priority=priority)
        return restful.ok()
    else:
        return restful.params_error(message=form.get_error())

@require_POST
def add_banner(request):
    """
    添加banner接口
    :param request:
    :return:
    """
    form = AddBannerForm(request.POST)
    if form.is_valid():
        priority = form.cleaned_data.get('priority')
        link_to = form.cleaned_data.get('link_to')
        image_url = form.cleaned_data.get('image_url')
        banner = Banner.objects.create(priority=priority, link_to=link_to, image_url=image_url)
        return restful.result(data={'banner_id': banner.pk})
    else:
        return restful.params_error(message=form.get_error())

class ArticleListView(View):
    def get(self, request):
        page = int(request.GET.get('page', 1))
        start = request.GET.get('start')
        end = request.GET.get('end')
        title = request.GET.get('title')
        categoryId = int(request.GET.get('category') or 0)
        articles = Article.objects.select_related('author', 'category').exclude(delete=True)
        if start or end:
            start_date = make_aware(datetime.strptime(start, '%Y/%m/%d') if start else datetime(2018,8,23))
            end_date = make_aware(datetime.strptime(end, '%Y/%m/%d') if end else datetime.now())
            articles = articles.filter(pub_time__range=(start_date, end_date))
        if title:
            articles = articles.filter(title__icontains=title)
        if categoryId:
            articles = articles.filter(category_id=categoryId)
        paginator = Paginator(articles, 2)
        page_obj = paginator.page(page)
        context_data = self.get_pagination_data(paginator, page_obj)
        categories = ArticleCategory.objects.all()
        context = {
            'articles': page_obj.object_list,
            'categories': categories,
            'page_obj': page_obj,
            'paginator': paginator,
            'start': start,
            'end': end,
            'title': title,
            'categoryId': categoryId,
            'url_query': parse.urlencode({
                'start': start or '',
                'end': end or '',
                'category': categoryId or ''
            })
        }
        context.update(context_data)
        return render(request, 'cms/article_list.html', context=context)

    def get_pagination_data(self,paginator,page_obj,around_count=2):
        current_page = page_obj.number
        total_page = paginator.num_pages
        left_has_more = False
        right_has_more = False
        if current_page <= around_count + 2:
            left_pages = range(1,current_page)
        else:
            left_has_more = True
            left_pages = range(current_page-2,current_page)
        if current_page >= total_page - around_count - 1:
            right_pages = range(current_page + 1,total_page + 1)
        else:
            right_has_more = True
            right_pages = range(current_page+1,current_page+around_count+1)
        return {
            'current_page': current_page,
            'left_pages': left_pages,
            'right_pages': right_pages,
            'left_has_more': left_has_more,
            'right_has_more': right_has_more
        }

def ad_list(request):
    return render(request, 'cms/advertisement.html')

@require_POST
def upload_file(request):
    """
    上传文件到服务器接口
    :param request:
    :return: 图片路径
    """
    file = request.FILES.get('file')
    name = file.name
    with open(os.path.join(settings.MEDIA_ROOT, name), 'wb') as fp:
        for chunk in file.chunks():
            fp.write(chunk)
    url = request.build_absolute_uri(settings.MEDIA_URL + name)
    return restful.result(data={
        'url': url
    })

@require_POST
def juhesign(request):
    """
    返回聚合图床签名
    :param request:
    :return:
    """
    cur_timestamp = int(time.time())
    sign = hashlib.md5((settings.JH_ID + "-" + settings.JH_TOKEN + "-" + str(cur_timestamp)).encode('utf-8'))
    return restful.ok(data={
        'sign': sign.hexdigest(),
        'id': settings.JH_ID,
        'ts': cur_timestamp
    })
